package com.example.giteeoauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequestEntityConverter;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequestEntityConverter;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Component;

import java.net.URI;


@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public ClientRegistrationRepository clientRepository() {
        ClientRegistration c = clientRegistration();
        return new InMemoryClientRegistrationRepository(c);
    }

//    private ClientRegistration clientRegistration() {
//        return CommonOAuth2Provider.GITHUB.getBuilder("github")
//                .clientId("a7553955a0c534ec5e6b")
//                .clientSecret("1795b30b425ebb79e424afa51913f1c724da0dbb")
//                .build();
//    }

    private ClientRegistration clientRegistration() {
        ClientRegistration cr = ClientRegistration.withRegistrationId("gitee")
            .clientId("513f175cb7410dd74ea2e7d3987239b6dc5294d52a2d48b2091cc9bba654c77e")
            .clientSecret("86cdc391480582209feda829cecadef4d86534ec8a28e80c35893556c1b72014")
            .scope(new String[]{"user_info"})
            .authorizationUri("https://gitee.com/oauth/authorize")
            .tokenUri("https://gitee.com/oauth/token")
            .userInfoUri("https://gitee.com/api/v5/user")
            .userNameAttributeName("name")
            .clientName("Gitee")
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}")
            .build();
        return cr;

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.oauth2Login()
            .tokenEndpoint()
                .accessTokenResponseClient(this.accessTokenResponseClient())
            .and()
            .userInfoEndpoint()
                .userService(this.auth2UserService());

        http.authorizeRequests()
            .antMatchers("/").permitAll()
            .anyRequest().authenticated();

    }

    /**
     * 解决获取AccessToken需要携带user-agent头的问题
     * @return
     */
    @Bean
    public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient(){
        DefaultAuthorizationCodeTokenResponseClient provider = new DefaultAuthorizationCodeTokenResponseClient();
        provider.setRequestEntityConverter(new OAuth2AuthorizationCodeGrantRequestEntityConverter() {
            @Override
            public RequestEntity<?> convert(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) {

                RequestEntity<?> convert = super.convert(authorizationCodeGrantRequest);
                if(authorizationCodeGrantRequest.getClientRegistration().getRegistrationId().equals("gitee")) {
                    HttpHeaders headers = new HttpHeaders();
                    //加上user-agent头
                    headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
                    headers.addAll(convert.getHeaders());
                    return new RequestEntity<>(convert.getBody(), headers,HttpMethod.POST,convert.getUrl());

                }
                return convert;
            }
        });

        return provider;
    }

    /**
     * 解决获取userinfo需要将AccessToken放在query string中的问题
     * @return
     */
    @Bean
    public OAuth2UserService<OAuth2UserRequest, OAuth2User> auth2UserService() {
        DefaultOAuth2UserService defaultOAuth2UserService = new DefaultOAuth2UserService();
        defaultOAuth2UserService.setRequestEntityConverter(new OAuth2UserRequestEntityConverter() {
            @Override
            public RequestEntity<?> convert(OAuth2UserRequest userRequest) {

                RequestEntity<?> convert = super.convert(userRequest);
                if(userRequest.getClientRegistration().getRegistrationId().equals("gitee")) {
                    HttpHeaders headers = new HttpHeaders();
                    headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
                    headers.addAll(convert.getHeaders());

                    //加上access_token queryString
                    return new RequestEntity<>(convert.getBody(), headers, HttpMethod.GET,
                        URI.create(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri()+"?access_token="+userRequest.getAccessToken().getTokenValue()));

                }
                return convert;
            }
        });
        return defaultOAuth2UserService;
    }
}
